﻿Imports System.Reflection

Friend Class MetaData

    Private Domain As AppDomain = Nothing
    Private Agent As DomainAgent = Nothing
    Private root As List(Of Types)
    Public EmptyType As Types

    Public Sub New()
        root = New List(Of Types)
    End Sub

    Public Function GetThisType(ByVal Name As String) As Types
        For Each T As Types In root
            If T.Name.ToLower = Name.ToLower Then
                Return T
            End If
        Next
        Return EmptyType
    End Function

    Public Function GetValidType() As String()
        Dim TheTypes As New List(Of String)
        For Each T As Types In root
            TheTypes.Add(T.Name)
        Next
        Return TheTypes.ToArray
    End Function

    Public Function IsValidType(ByVal Name As String) As Boolean
        For Each T As Types In root
            If T.Name.ToLower = Name.ToLower Then Return True
        Next
        Return False
    End Function

    Public Function IsMethodOf(ByVal [Class] As String, ByVal Method As String) As Boolean
        Dim Typ As Types = GetThisType([Class])
        If Not Typ.Equals(Me.EmptyType) Then
            For Each M As Methods In Typ.Methods
                If M.Name.ToLower = Method.ToLower Then Return True
            Next
        End If
        Return False
    End Function

    Public Function IsPropertyOf(ByVal [Class] As String, ByVal [Property] As String) As Boolean
        Dim Typ As Types = GetThisType([Class])
        If Not Typ.Equals(Me.EmptyType) Then
            For Each M As Properties In Typ.Properties
                If M.Name.ToLower = [Property].ToLower Then Return True
            Next
        End If
        Return False
    End Function

    Public Sub AddReference(ByVal AssemblyPath As String)
        Domain = AppDomain.CreateDomain("Domain")
        Agent = CType(Domain.CreateInstanceAndUnwrap(GetType(DomainAgent).Assembly.GetName().FullName, _
                                                        GetType(DomainAgent).FullName), DomainAgent)
        Agent.AddMetaData(AssemblyPath, root)
        AppDomain.Unload(Domain)
    End Sub

    Private Class DomainAgent : Inherits MarshalByRefObject

        Public Sub AddMetaData(ByVal AssemblyPath As String, ByRef Root As List(Of Types))

            Dim TheAssembly As Assembly = Assembly.LoadFrom(AssemblyPath)
            Dim ExportedTypes() As Type = TheAssembly.GetExportedTypes
            For Each _Type As Type In ExportedTypes
                Dim ThisType As New Types
                ThisType.Initialize()
                ThisType.Name = _Type.Name
                ThisType.NameSpace = _Type.Namespace
                ThisType.isClass = _Type.IsClass
                ThisType.isEnum = _Type.IsEnum
                If _Type.IsEnum Then
                    Dim EnumName() As String = _Type.GetEnumNames
                    For Each Name As String In EnumName
                        '===Add other info
                    Next
                Else
                    Dim exportedMethod() As MethodInfo = _Type.GetMethods
                    For Each _Method As MethodInfo In exportedMethod
                        Dim ThisMethod As New Methods
                        ThisMethod.Name = _Method.Name
                        '===Add other info

                        ThisType.Methods.Add(ThisMethod)
                    Next

                    Dim exportedFields() As FieldInfo = _Type.GetFields
                    For Each _field As FieldInfo In exportedFields
                        Dim ThisField As New Fields
                        ThisField.Name = _field.Name
                        '===Add other info

                        ThisType.Fields.Add(ThisField)
                    Next

                    Dim exportedProperty() As PropertyInfo = _Type.GetProperties
                    For Each _Property As PropertyInfo In exportedProperty
                        Dim ThisProperty As New Properties
                        ThisProperty.Name = _Property.Name
                        '===Add other info

                        ThisType.Properties.Add(ThisProperty)
                    Next

                    Dim exportedEvent() As EventInfo = _Type.GetEvents
                    For Each _Event As EventInfo In exportedEvent
                        Dim ThisEvent As New Events
                        ThisEvent.Name = _Event.Name
                        '===Add other info

                        ThisType.Events.Add(ThisEvent)
                    Next

                    Dim exportedInterfaces() As Type = _Type.GetInterfaces
                    For Each _Interface As Type In exportedInterfaces
                        Dim ThisInterface As New Interfaces
                        ThisInterface.Name = _Interface.Name
                        '===Add other info
                        ' ThisType got to point to an existing type
                        ThisType.Interfaces.Add(ThisInterface)
                    Next

                    Dim exportedGenericArgument() As Type = _Type.GetGenericArguments
                    For Each _GenericArgument As Type In exportedGenericArgument
                        Dim ThisGenericArgument As New GenericArguments
                        ThisGenericArgument.Name = _GenericArgument.Name
                        '===Add other info
                        ' ThisType got to point to an existing type
                        ThisType.GenericArguments.Add(ThisGenericArgument)
                    Next

                    'Const ???

                    Dim exportedNestedType() As Type = _Type.GetNestedTypes
                    For Each _NestedType As Type In exportedNestedType
                        ' ThisType got to point to an existing type
                        ' Nested type may also have nested type
                    Next

                End If
                Root.Add(ThisType) ' <--Serialize in this domain and deserialize in the other domain
            Next
        End Sub

    End Class
End Class



<Serializable()>
Public Structure Types
    Public Sub Initialize()
        Methods = New List(Of Methods)
        Fields = New List(Of Fields)
        Properties = New List(Of Properties)
        NestedType = New List(Of Types)
        Constant = New List(Of String)
        EnumFields = New List(Of EnumFields)
        Events = New List(Of Events)
        GenericArguments = New List(Of GenericArguments)
        Interfaces = New List(Of Interfaces)
    End Sub
    Dim Name As String
    Dim [NameSpace] As String
    Dim isClass As Boolean
    Dim isEnum As Boolean
    Dim Methods As List(Of Methods)
    Dim Fields As List(Of Fields)
    Dim Properties As List(Of Properties)
    Dim NestedType As List(Of Types)
    Dim Constant As List(Of String)
    Dim EnumFields As List(Of EnumFields)
    Dim Events As List(Of Events)
    Dim GenericArguments As List(Of GenericArguments)
    Dim Interfaces As List(Of Interfaces)
End Structure

<Serializable()>
Public Structure Methods
    Dim Name As String

End Structure

<Serializable()>
Public Structure Fields
    Dim Name As String

End Structure

<Serializable()>
Public Structure Properties
    Dim Name As String

End Structure

<Serializable()>
Public Structure EnumFields
    Dim Name As String
    ' Dim Value As Integer
End Structure

<Serializable()>
Public Structure ConstFields
    Dim Name As String
    ' Dim Value As Integer
End Structure

<Serializable()>
Public Structure Events
    Dim Name As String
    ' Dim Value As Integer
End Structure

<Serializable()>
Public Structure Interfaces
    Dim Name As String
    ' Dim Value As Integer
End Structure

<Serializable()>
Public Structure GenericArguments
    Dim Name As String
    ' Dim Value As Integer
End Structure

